from common.CommonNode import CommonNode
from common.CommonHeap import CommonHeap


class Node(CommonNode):
    def __init__(self, size, start, obj):
        super().__init__(size, start, obj)
        self.referCnt = 0

    def incrReferCnt(self):
        self.referCnt += 1

    def decReferCnt(self):
        self.referCnt -= 1

    def getRefer(self):
        return self.referCnt


class Heap:
    def __init__(self, size):
        self.heapStart = Node(size, 0, None)
        self.size = size
        self.usedSize = 0
        self.chunk = 1

    def __str__(self):
        return f"total: {self.size}, used: {self.usedSize}, chunk: {self.chunk}"

    def newObject(self, size, obj):
        nd, addChunk = CommonHeap.firstFit(self.heapStart, size, Node)
        if nd is None:
            raise Exception("分配失败")
        nd.setObj(obj)
        nd.incrReferCnt()
        self.usedSize += size
        self.chunk += addChunk
        return nd

    def freeObject(self, node):
        self.usedSize -= node.getSize()
        decChunk = CommonHeap.freeObject(node)
        self.chunk -= decChunk

    @staticmethod
    def reference(nodeA: Node, nodeB: Node):
        nodeB.incrReferCnt()
        nodeA.addChild(nodeB)

    def unReference(self, nodeA: Node, nodeB: Node):
        nodeB.decReferCnt()
        if nodeB.getRefer() == 0:
            for cld in nodeB.getChildren():
                self.unReference(nodeB, cld)
            self.freeObject(nodeB)


if __name__ == '__main__':
    heap = Heap(1024)
    n0 = heap.newObject(10, "123")
    n1 = heap.newObject(10, "addd")
    heap.reference(n0, n1)
    heap.unReference(None, n0)
    heap.unReference(None, n1)
    print(heap)

